﻿
Imports std
Imports storoomc

Public MustInherit Class storoomOper_fixpoint(Of T As comparableStorageInterface(Of T))
    Inherits storoomOper

    Protected listmap As map(Of String, [set](Of T)) = Nothing

    Private Function insertlistmapImpl(ByVal key As String, ByVal slice As storageInterface) As Boolean
        Dim slices As [set](Of T) = Nothing
        slices = listmap(key)
        slices.insert(slice)
        cacheUpdater.seek(key, True)

        Return True
    End Function

    Private Function _set2vector(ByVal i As [set](Of T)) As vector(Of storageInterface)
        If i Is Nothing Then
            Return Nothing
        Else
            Dim rtn As vector(Of storageInterface) = Nothing
            rtn = New vector(Of storageInterface)()
            Dim it As [set](Of T).iterator = Nothing
            it = i.begin()
            While it <> i.end()
                rtn.push_back(+it)
                it += 1
            End While

            Return rtn
        End If
    End Function

    Protected Function insertlistmap(ByVal key As String, ByVal slice As storageInterface) As Boolean
        Dim rtn As Boolean = True
        SyncLock listmap
            rtn = insertlistmapImpl(key, slice)
        End SyncLock

        Return rtn
    End Function

    Protected Function insertlistmap(ByVal key As String, _
                                     ByVal slices As vector(Of storageInterface)) As Boolean
        Dim i As Int32
        Dim rtn As Boolean = True
        SyncLock listmap
            For i = 0 To slices.size() - 1
                rtn = rtn And insertlistmapImpl(key, slices(i))
            Next
        End SyncLock

        Return rtn
    End Function

    Protected Function insertlistmap(ByVal keys As vector(Of String), _
                                     ByVal slice As storageInterface) As Boolean
        Dim rtn As Boolean = True
        SyncLock listmap
            Dim i As Int64
            For i = 0 To keys.size() - 1
                rtn = rtn And insertlistmapImpl(keys(i), slice)
            Next
        End SyncLock

        Return rtn
    End Function

    Protected Function removelistmap(ByVal key As String) As Boolean
        SyncLock listmap
            Return listmap.erase(key)
        End SyncLock

        Return True
    End Function

    Private Function _seekkey(ByVal key As String) As [set](Of T)
        Dim work As map(Of String, [set](Of T)).iterator = Nothing
        Dim rtn As [set](Of T) = Nothing
        SyncLock listmap
            work = listmap.find(key)
            If work <> listmap.end() Then
                copy(rtn, (+work).second)
            End If
        End SyncLock

        Return rtn
    End Function

    Private Function slicehealth(ByVal slice As storageInterface) As Boolean
        assert(Not slice Is Nothing, "slice is nothing.")
        Dim it As map(Of String, [set](Of T)).iterator = Nothing
        it = listmap.begin()
        Dim trytimes As Int64 = (slices.size() << 4)
        While trytimes > 0 AndAlso it <> listmap.end()
            Dim it2 As [set](Of T).iterator = Nothing
            it2 = (+it).second.begin()
            While it2 <> (+it).second.end()
                If Object.ReferenceEquals((+it2), slice) Then
                    Exit While
                End If
            End While
            it += 1
            trytimes -= 1
        End While

        'not found any slice related to input slice, so import its list.
        If trytimes = 0 OrElse it = listmap.end() Then
            raiseError("caught the healthStatus changed to health, " + _
                       "will import its list again. slice " + showslice(slice))
            Dim list As vector(Of String) = Nothing
            If Not slice Is Nothing AndAlso slice.list(list) Then
                cacheUpdater.capacityClear()
                cacheUpdater.empty(False)
                Return insertlistmap(list, slice)
            Else
                raiseError("cannot list from slice " + showslice(slice), errorHandle.errorType.exclamation)
                Return False
            End If
        Else
            Return True
        End If
    End Function

    Protected Overloads Sub startImpl(ByVal reimportListAfterHealth As Boolean)
        MyBase.start()
        listmap = New map(Of String, [set](Of T))
        listImpl()
        If reimportListAfterHealth Then
            sliceHealthHandle = AddressOf slicehealth
        End If
    End Sub

    Public Overrides Sub start()
        startImpl(True)
    End Sub

    Protected Overrides Function writeImpl(ByVal key As String, ByVal buff As bytes, _
                                           ByRef slice As storageInterface, _
                                           ByVal slices As vector(Of storageInterface)) As Boolean
        If (Not slices Is Nothing AndAlso slices.size() > 0 AndAlso MyBase.writeImpl(key, buff, slice, slices)) OrElse
           MyBase.writeImpl(key, buff, slice, Me.slices) Then
            Return insertlistmap(key, slice)
        Else
            Return False
        End If
    End Function

    Protected Overrides Function deleteImpl(ByVal key As String, _
                                            ByVal slices As vector(Of storageInterface)) As Boolean
        If MyBase.deleteImpl(key, slices) Then
            If Not removelistmap(key) Then
                raiseError("cannot remove listmap relation, key " + key, errorHandle.errorType.warning)
            End If
            Return True
        Else
            Return False
        End If
    End Function

    Protected Overrides Function retireImpl(ByVal slices As vector(Of storageInterface)) As Boolean
        If MyBase.retireImpl(slices) Then
            SyncLock listmap
                listmap.clear()
            End SyncLock
            Return True
        Else
            Return False
        End If
    End Function

    Private Overloads Function listImpl() As Boolean
        If threadModel().multiOper(Function(ByRef s As storageInterface) As ternary
                                       Dim tmp As vector(Of String) = Nothing
                                       If s.list(tmp) Then
                                           Return insertlistmap(tmp, s)
                                       Else
                                           Return ternary.false
                                       End If
                                   End Function, slices) Then
            raiseError("finish import list from stornodes.")
            Return True
        Else
            raiseError("cannot finish listImpl operation", errorHandle.errorType.exclamation)
            Return False
        End If
    End Function

    Protected Overrides Function listImpl(ByVal l As vector(Of String), _
                                          ByVal slices As vector(Of storageInterface)) As Boolean
        Dim work As map(Of String, [set](Of T)).iterator = Nothing
        work = listmap.begin()
        While work <> listmap.end()
            assert(l.push_back((+work).first), "l.insert(work.key) returns false.")
            work += 1
        End While

        Return True
    End Function

    Protected Overrides Function selectkeySlices(ByVal key As String) As vector(Of storageInterface)
        Dim s As [set](Of T) = Nothing
        s = _seekkey(key)
        Return _set2vector(s)
    End Function

    Protected Overrides Function seekImpl(ByVal key As String, ByVal slices As vector(Of storageInterface)) As ternary
        Return Not slices Is Nothing AndAlso slices.size() > 0
    End Function

    Protected Overrides Function modifyImpl(ByVal key As String, ByVal buff As bytes, _
                                            ByRef slice As storageInterface, _
                                            ByVal slices As vector(Of storageInterface)) As Boolean
        If randomSelectModify(key, buff, slice, slices) Then
            If Not insertlistmap(key, slice) Then
                raiseError("cannot insert listmap relation, may cause data lost. key " + key, _
                           errorHandle.errorType.warning)
            End If
            Return True
        Else
            Return False
        End If
    End Function

    Protected Overrides Function keycountImpl(ByRef count As UInt64, _
                                              ByVal slices As vector(Of storageInterface)) As Boolean
        count = listmap.size()
        Return True
    End Function

    Protected Overrides Function emptyImpl(ByVal slices As vector(Of storageInterface)) As ternary
        Return listmap.empty()
    End Function
End Class
